<?php
/**
 * Created by PhpStorm.
 * Author: 芸签cms www.yunqiancms.com
 * User: sun
 * Date: 2022/6/23
 * Time: 3:03 PM
 */
namespace app\common\models;

use app\common\helpers\Cache;
use Illuminate\Support\Arr;

class Setting extends BaseModel
{
    public $table = 'yq_setting';

    public $timestamps = false;

    public $guarded = [''];

    public $defaultGroup = 'cms';

    const CACHE_KEY_PRE = 'app:common:facades:setting:';

    /**
     * 获取配置
     *
     * @param $uniqueAccountId
     * @param $key
     * @param null $default 默认值
     * @return mixed
     */
    public function getValue($key, $default = null)
    {
        $cacheKey = self::CACHE_KEY_PRE.$key;
        /*if(Cache::has($cacheKey)){
            \Log::debug('getSettingValue use cache...');
            return Cache::get($cacheKey);
        }*/
        list($group, $groupKey) = $this->parseKey($key);
        $settingGroupItems = $this->getItems($group);
        $value = Arr::get($settingGroupItems, $groupKey, $default);
        Cache::put($cacheKey,$value,60);
        return $value;
    }

    /**
     * 设置配置值.
     *
     * @param $uniqueAccountId
     * @param string $key 键 使用.隔开 第一位为group
     * @param mixed $value 值
     *
     * @return mixed
     */
    public function setValue($key, $value = null)
    {
        list($group, $item) = $this->parseKey($key);

        $type = $this->getTypeOfValue($value);

        $result = $this->setToDatabase($value, $group, $item, $type);
        if ($type == 'array') {
            $value = unserialize($value);
        }
        Cache::put(self::CACHE_KEY_PRE.$key,$value,60);
        return $result;
    }
    /**
     * 解析key
     * 分离出 group 与真正的key,其中.分隔第一个为group
     * @param $key
     * @return array
     */
    protected function parseKey($key)
    {
        $explodedOnGroup = explode('.', $key);
        if (count($explodedOnGroup) > 1) {
            $group = array_shift($explodedOnGroup);
            $item = implode('.', $explodedOnGroup);
        } else {
            $group = $this->defaultGroup;
            $item = $explodedOnGroup[0];
        }

        return [$group, $item];
    }
    /**
     * 获取值的类型 并设置值为序列化
     *
     * @param $value
     * @return null|string
     */
    protected function getTypeOfValue(&$value)
    {
        $type = null;
        $givenType = strtolower(gettype($value));

        switch ($givenType) {
            case 'string':
            case 'integer':
            case 'double':
            case 'boolean':
            case 'null':
                $type = $givenType;
                break;
            case 'array':
                $value = serialize($value);
                $type = 'array';
                break;
            default:
                $type = null;
        }
        return $type;
    }

    /**
     * 格式化并保存配置到数据库
     * @param $value
     * @param $uniqueAccountId
     * @param $group
     * @param $key
     * @param $type
     * @return static
     */
    protected function setToDatabase($value, $group, $key, $type)
    {

        //检测数组是否需要特殊操作
        $arrayHandling = false;
        $keyExploded = explode('.', $key);
        if (count($keyExploded) > 1) {
            $arrayHandling = true;
            $key = array_shift($keyExploded);
            if ($type == 'array') {
                $value = unserialize($value);
            }
        }

        //如果存在记录则更新
        $model = self::site()
            ->where('key', $key)
            ->where('group', $group);
        $model = $model->first();

        if (!$model) {
            //新增数据
            $model = new Setting();
            $model->site_id = \YunCms::siteId();
            $model->group = $group;
            $model->key = $key;

        }
        if ($arrayHandling) {
            //如果数组需要特殊操作
            $array = array();
            self::buildArrayPath($keyExploded, $value, $array);
            //如果是数组则合并，只有编辑的时候才用到
            if ($model->type == 'array') {
                $array = array_replace_recursive(unserialize($model->value), $array);
            }
            $value = serialize($array);

            $type = 'array';
        }
        $model->value = $value;
        $model->type = $type;
        return $model->save();
    }
    /**
     * 获取账号内当前组的所有配置信息
     *
     * @param $uniqueAccountId
     * @param $group
     * @return array
     */
    public function getItems($group)
    {
        $items = array();
        $settings = self::site()->select()
            ->where('group', $group)
            ->get();;
        foreach ($settings as $item) {
            switch (strtolower($item->type)) {
                case 'string':
                    $items[$item->key] = (string)$item->value;
                    break;
                case 'integer':
                    $items[$item->key] = (integer)$item->value;
                    break;
                case 'double':
                    $items[$item->key] = (double)$item->value;
                    break;
                case 'boolean':
                    $items[$item->key] = (boolean)$item->value;
                    break;
                case 'array':
                    $items[$item->key] = unserialize($item->value);
                    break;
                case 'null':
                    $items[$item->key] = null;
                    break;
                default:
                    $items[$item->key] = $item->value;
            }
        }
        return $items;
    }
    /**
     * 配置信息格式化数组
     * @param $array
     * @param $key
     * @param $value
     * @return mixed
     */
    private function fmtArraySetting($array, $key, $value)
    {
        $keys = explode('.', $key);
        while (count($keys) > 1) {
            $key = array_shift($keys);

            // If the key doesn't exist at this depth, we will just create an empty array
            // to hold the next value, allowing us to create the arrays to hold final
            // values at the correct depth. Then we'll keep digging into the array.
            if (!isset($array[$key]) || !is_array($array[$key])) {
                $array[$key] = [];
            }
            $array = &$array[$key];
        }
        $array[array_shift($keys)] = $value;

        return $array;
    }
    /**
     * 组合数组
     *
     * @param $map
     * @param $value
     * @param $array
     */
    protected static function buildArrayPath($map, $value, &$array)
    {
        $key = array_shift($map);
        if (count($map) !== 0) {
            $array[$key] = array();
            self::buildArrayPath($map, $value, $array[$key]);
        } else {
            $array[$key] = $value;
        }
    }
}